/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package models;

import config.Models.Conf_User;
import db.Redis_Rd;
import db.Redis_W;
import java.util.HashMap;
import java.util.Map;
import share.KeysDefinition;
import share.ShareMacros;
import entities.User;
import java.util.Set;

/**
 *
 * @author LinhTA
 */
public class UserModel implements BaseModel 
{
    public U_CoteModel cotes;
    public U_FriendModel friends;
    public int level;
    public int fish;
    public int gold;
    public int coin;
    public int exp;
    public long timeLogin;
    public String name;
    public String avata;
    public int helpFood;
    public int helpDay;
    public String uid;
    public String coteId;

    public UserModel( String uid )
    {
        this.uid    =   uid;
    }
    
    @Override
    public void setDB() 
    {
    }

    @Override
    public void setData(Map<String, String> obj) 
    {
        User u = new User();
        u.setUser(obj);
    }

    @Override
    public void getDB(String uid) 
    {
    }

    public static Boolean isNewUser(String uid) 
    {
        int f = 3;

        String key = KeysDefinition.getKeyUser(uid);
        while (f >= 0) {
            boolean getKey, getKeys;
            getKey = Redis_Rd.getInstance().isExits(key);
            getKeys = Redis_Rd.getInstance().sismember(KeysDefinition.getKeyUserList(), key) != 0;

            f--;
            if (getKey == false && getKeys == false) {
                return true;
            }
        }

        return false;
    }

    public Map<String, Object> getDataUser() 
    {
        Map<String, Object> data;

        if ( UserModel.isNewUser(uid) ) 
        {
            User u = new User();
            setDBNewUser( u );
            setDataNewUser( u );
            data = toAMF();
        } 
        else 
        {
            getDataOldUser();
            data = toAMF();
        }
        return data;
    }

    public void setDataNewUser( User u ) 
    {
        level = u.level;
        fish = u.fish;
        gold = u.gold;
        coin = u.coin;
        exp = u.exp;
        timeLogin = u.timeLogin;
        name = u.name;
        avata = u.avata;
        helpFood = u.helpFood;
        helpDay = u.helpDay;

        friends = U_FriendModel.isNewUser(uid);
        cotes = U_CoteModel.isNewUser(uid);
    }

    public Map<String, Object> toAMF() 
    {
        Map<String, Object> data = new HashMap<String, Object>();

        data.put(ShareMacros.LEVEL, level);
        data.put(ShareMacros.FISH, fish);
        data.put(ShareMacros.GOLD, gold);
        data.put(ShareMacros.COIN, coin);
        data.put(ShareMacros.EXP, exp);
        data.put(ShareMacros.TIMELOGIN, timeLogin);
        data.put(ShareMacros.USER_NAME, name);
        data.put(ShareMacros.USER_AVATA, avata);
        data.put(ShareMacros.USER_HELPFOOD, helpFood);
        data.put(ShareMacros.USER_HELPDAY, helpDay);

        data.put(ShareMacros.COTES, cotes.toAMF());

        return data;
    }

    public Map<String, Object> getDataOldUser() 
    {
        Map<String, Object> data = new HashMap<String, Object>();

        User u      =   getDBUser();

        level       =   u.level;
        fish        =   u.fish;
        gold        =   u.gold;
        coin        =   u.coin;
        exp         =   u.exp;
        timeLogin   =   u.timeLogin;
        name        =   u.name;
        avata       =   u.avata;
        helpFood    =   u.helpFood;
        helpDay     =   u.helpDay;

        U_FriendModel ufriendModel = new U_FriendModel(uid);
        ufriendModel.getDB(String.valueOf(uid));
        friends = ufriendModel;
        
        U_CoteModel uCoteModel = new U_CoteModel(uid);
        uCoteModel.getDB(String.valueOf(uid));
        cotes = uCoteModel;

        return data;
    }

    public User getDBUser() 
    {
        User u = new User();

        Map<String, String> data = Redis_Rd.getInstance().hget(KeysDefinition.getKeyUser(uid));
        u.setUser(data);
       
        return u;
    }

    public void setDBNewUser( User u ) 
    {
        String keyUser = KeysDefinition.getKeyUser(uid);
        if (Redis_W.getInstance().sadd(KeysDefinition.getKeyUserList(), keyUser) != -1) {

            String keyFriends = KeysDefinition.getKey_ListFriends(uid);
            String keyCotes = KeysDefinition.getKey_ListCotes(uid);

            name    =   FakeData.getName(uid);
            avata   =   FakeData.getAvata(uid);

            Map<String, String> data;
            u.setDefaultData(keyCotes, keyFriends, name, avata);
            data = u.getDefaultData();

            System.out.print(Redis_W.getInstance().hset(keyUser, data));
        }
    }

    //================ hieubnd=========
    /*
     * check is valid user
     */
    public static boolean isExist( String uid ) 
    {
        String keyUser = KeysDefinition.getKeyUser( uid );
        return Redis_Rd.getInstance().isExits( keyUser );
    }
    
    /*
     * Is cote belong to user
     */
    public boolean isValidCote( String coteId ) 
    {
        
        if( isExist(uid) ) {
            User u  =   getDBUser();
            Set<String> cotes   =   Redis_Rd.getInstance().smember( u.cotes );
            if( cotes.contains( coteId )) {
                return true;
            }
        }
        return false;
    }
    
    /*
     * Update all user DB information
     */
    public void updateDBUser( User u ) 
    {
        String keyUser  =   KeysDefinition.getKeyUser(uid);
        Map<String, String> currentUserModel    =   u.getDefaultData();
        Redis_W.getInstance().hset( keyUser, currentUserModel );
    }
    
    /*
     * Update user level by increase one
     */
    public boolean increaseLevelByOne() 
    {
        boolean result;
        
        User u          =   getDBUser();
        
        int nextLvl     =   u.level + 1;
        Long nextExp;
        HashMap<String, Conf_User> conf =    config.ConfigModels.conf_user;
        Map<String, Object> expTree     =    conf.get("user").expTree;
        nextExp         =   (Long)expTree.get( String.valueOf( nextLvl ) );
        
        if( nextExp < u.exp ) {
            result      =   true;
            u.level  +=  1;
            this.updateDBUser( u );
        } else
            result      =   false;
        
        return result;
    }
    
    /*
     * Update user exp by increase nExp
     * @param nExp: number of Exp want to increase
     */
    public void increaseUserExp( int nExp ) 
    {
        
        User user   =   getDBUser();
        if( user == null )
            return ;
        
        user.exp    += nExp;
        updateDBUser( user );
    }
    
    /*
     * Update user gold 
     * @param toGold: gold user need to update
     */
    public boolean updateUserGold( int toGold ) 
    {
        boolean result  =   false;
        
        User user   =   getDBUser();
        if( user == null )
            return result;
        
        user.gold   =   toGold;
        updateDBUser( user );
        result      =   true;
        
        return result;
    }
    
    /*
     * Update user gold 
     * @param nGold: number of gold user increase
     */
    public boolean increaseUserGold( int nGold ) 
    {
        boolean result  =   false;
        
        User user       =   getDBUser();
        if( user == null )
            return result;
        
        user.gold   +=   nGold;
        updateDBUser( user );
        result      =   true;
        
        return result;
    }
    
    /*
     * Update user coin 
     * @param toCoin: coin user need to update
     */
    public boolean updateUserCoin( int toCoin ) 
    {
        boolean result  =   false;
        
        User user       =   getDBUser();
        if( user == null )
            return result;
        
        user.coin   =   toCoin;
        updateDBUser( user );
        result      =   true;
        
        return result;
    }
    
    /*
     * Update user coin 
     * @param nCoin: number of coin user increase
     */
    public boolean increaseUserCoin( int nCoin ) 
    {
        boolean result  =   false;
        
        User user       =   getDBUser();
        if( user == null )
            return result;
        
        user.coin   +=   nCoin;
        updateDBUser( user );
        result      =   true;
        
        return result;
    }
    //================ hieubnd=========
}
